import { Emitter } from '@/utils/Emitter';
import {
  registerHealthCardPreAuth,
  registerHealthCardPreFill,
  healthCardByHealthCode,
  getRegInfoByCode,
  getOrderInfoByOrderId,
  registerRealPersonAuthOrder,
  registerUniformVerifyOrder,
  checkUniformVerifyResult,
  getDynamicQrCode,
} from '@/apis/healthCard';
import { addHealthCard, updateHealthCard } from '@/apis/patient';
import healthCardUtil from '@/utils/healthCard/index';
import { cloneDeep } from 'lodash-es';

const plugin = requirePlugin('healthCardPlugins');

/* 绑卡回调地址 */
const BindSuccessRedirectUrl =
  'mini:/patientPages/healthCard/redirectUrl/index?healthCode=${healthCode}';

const BindFailRedirectUrl =
  'mini:/patientPages/healthCard/redirectUrl/index?regInfoCode=${regInfoCode}';

const BindUserFormPageUrl =
  'mini:/patientPages/healthCard/useFrom/index?authCode=${authCode}';

// 人脸识别
const FaceRedirectUrl = '/patientPages/healthCard/faceUrl/index';

const VerifySuccessRedirectUrl =
  'mini:/patientPages/healthCard/verifyUrl/index?registerOrderId=${registerOrderId}';

// 验证失败
const VerifyFailRedirectUrl = 'mini:/patientPages/healthCard/failUrl/index';

// 腾讯电子健康卡
class ElectronicHealthCard {
  // 授权
  authEmitter;
  // 微信用户唯一标识，需通过uni.login获取
  wechatCode = '';
  // 建档地址
  createURL = '';
  // 升级地址
  updateURL = '';
  // 绑定验证地址
  bindVerifyURL = '';
  // 查询验证地址
  searchVerifyURL = '';
  // 结果
  healthCode = '';
  regInfoCode = '';
  // 记录健康卡信息
  healthCardInfo = {};
  constructor() {
    this.authEmitter = new Emitter();
  }
  loadWechatCode() {
    return new Promise((resolve, reject) => {
      plugin.login(
        (isok, res) => {
          healthCardUtil.log('【loadWechatCode 结果】 ', isok, res.result);
          if (!isok && res.result.toLogin) {
            reject(res);
          } else {
            // 用户在微信授权过，可直接获取登录信息，处理后续业务
            resolve(res.result.wechatCode);
          }
        },
        {
          wechatCode: true,
          // healthCode: true,
          // ecardNo: '',
        },
      );
    });
  }

  // 获取建档地址
  beforeCreateCard({ wechatCode }) {
    return new Promise((resolve, reject) => {
      healthCardUtil.log('【beforeCreateCard】');
      if (!wechatCode) {
        healthCardUtil.toast('wechatCode 不存在');
        return reject(new Error('wechatCode 不存在'));
      }
      // 入参
      const params = {
        wechatCode,
        patientType: 0,
        successRedirectUrl: BindSuccessRedirectUrl,
        failRedirectUrl: BindFailRedirectUrl,
        userFormPageUrl: BindUserFormPageUrl,
        verifyFailRedirectUrl: VerifyFailRedirectUrl,
        faceUrl: FaceRedirectUrl,
      };
      healthCardUtil.log('【registerHealthCardPreAuth 参数】', params);
      registerHealthCardPreAuth(params)
        .then(res => {
          healthCardUtil.log('【registerHealthCardPreAuth 结果】', res);
          if (res.data) {
            this.createURL = res.data;
            resolve && resolve(this.createURL);
          } else {
            healthCardUtil.toast('地址不存在');
            reject(new Error('地址不存在'));
          }
        })
        .catch(err => {
          healthCardUtil.log('【registerHealthCardPreAuth 结果】', err);
          reject(err);
        });
    });
  }
  // 获取升级地址
  beforeUpdateCard({ wechatCode, patientId }) {
    return new Promise((resolve, reject) => {
      healthCardUtil.log('【beforeUpdateCard】');
      if (!wechatCode) {
        healthCardUtil.toast('wechatCode 不能为空');
        return reject(new Error(`wechatCode 不能为空`));
      }
      if (!patientId) {
        healthCardUtil.toast('patientId 不能为空');
        return reject(new Error(`patientId 不能为空`));
      }
      // 入参
      const params = {
        wechatCode,
        patientType: 1, // 老患者升级
        successRedirectUrl: this.generatePatientURL(
          BindSuccessRedirectUrl,
          patientId,
        ),
        failRedirectUrl: this.generatePatientURL(
          BindFailRedirectUrl,
          patientId,
        ),
        userFormPageUrl: this.generatePatientURL(
          BindUserFormPageUrl,
          patientId,
        ),
        verifyFailRedirectUrl: this.generatePatientURL(
          VerifyFailRedirectUrl,
          patientId,
        ),
        faceUrl: this.generatePatientURL(FaceRedirectUrl, patientId),
      };
      healthCardUtil.log('【registerHealthCardPreAuth 参数】', params);
      registerHealthCardPreAuth(params)
        .then(res => {
          healthCardUtil.log('【registerHealthCardPreAuth 结果】', res);
          this.updateURL = res.data;
          resolve(this.updateURL);
        })
        .catch(err => {
          healthCardUtil.log('【registerHealthCardPreAuth 结果】', err);
          reject(err);
        });
    });
  }
  // 填写建档信息
  createCard({ param, authCode, code, patientId }) {
    return new Promise((resolve, reject) => {
      healthCardUtil.log('【createCard】');
      // param 对应的参数请参考：https://open.tengmed.com/openAccess/docs/develop#113

      const params = {
        code,
        businessDataBody: {
          ...param,
          authCode,
          successRedirectUrl: this.generatePatientURL(
            BindSuccessRedirectUrl,
            patientId,
          ),
          failRedirectUrl: this.generatePatientURL(
            BindFailRedirectUrl,
            patientId,
          ),
          verifyFailRedirectUrl: this.generatePatientURL(
            VerifyFailRedirectUrl,
            patientId,
          ),
          faceUrl: this.generatePatientURL(FaceRedirectUrl, patientId),
        },
      };
      healthCardUtil.log('【registerHealthCardPreFill 参数】', params);
      registerHealthCardPreFill(params)
        .then(res => {
          healthCardUtil.log('【registerHealthCardPreFill 结果】', res);
          this.bindVerifyURL = res.data;
          resolve(this.bindVerifyURL);
        })
        .catch(err => {
          healthCardUtil.log('【registerHealthCardPreFill 结果】', err);
          reject(err);
        });
    });
  }

  // 获取验证地址
  beforeGenerateOrderIdVerify(param) {
    return new Promise((resolve, reject) => {
      healthCardUtil.log('registerUniformVerifyOrder 参数】', param);
      const params = {
        ...param,
        verifySuccessRedirectUrl: VerifySuccessRedirectUrl,
        verifyFailRedirectUrl: VerifyFailRedirectUrl,
        faceUrl: FaceRedirectUrl,
      };
      registerUniformVerifyOrder(params)
        .then(res => {
          healthCardUtil.log('registerUniformVerifyOrder 结果】', res);
          resolve(res);
        })
        .catch(err => {
          healthCardUtil.log('registerUniformVerifyOrder 结果】', err);
          reject(err);
        });
    });
  }

  checkVerify({ verifyOrderId, registerOrderId }) {
    return new Promise((resolve, reject) => {
      healthCardUtil.log('checkUniformVerifyResult 参数】', param);
      const param = {
        verifyOrderId,
        verifyResult: registerOrderId,
      };
      checkUniformVerifyResult(param)
        .then(res => {
          healthCardUtil.log('checkUniformVerifyResult 结果】', res);
          const { suc } = res.data;
          if (suc) {
            healthCardUtil.toast('验证成功');
            resolve(suc);
          } else {
            healthCardUtil.toast('验证失败');
            reject(new Error('验证失败'));
          }
        })
        .catch(err => {
          healthCardUtil.log('checkUniformVerifyResult 结果】', err);
          healthCardUtil.toast('验证失败');
          reject(err);
        });
    });
  }

  setHealthCode(healthCode) {
    this.healthCode = healthCode;
  }
  clearHealthCode() {
    this.healthCode = null;
  }

  setRegInfoCode(regInfoCode) {
    this.regInfoCode = regInfoCode;
  }
  clearRegInfoCode() {
    this.regInfoCode = null;
  }

  hasResult() {
    return this.healthCode || this.regInfoCode;
  }

  // 通过healthCode获取健康卡信息
  getInfoByHealthCode() {
    return new Promise((resolve, reject) => {
      if (!this.healthCode) {
        healthCardUtil.toast('healthCode 不存在');
        return reject(new Error('healthCode 不存在'));
      }
      const param = {
        healthCode: this.healthCode,
      };
      healthCardUtil.log('【healthCardByHealthCode 参数】', param);
      healthCardByHealthCode(param)
        .then(res => {
          healthCardUtil.log('【healthCardByHealthCode 结果】', res);
          this.clearHealthCode();
          resolve(res);
        })
        .catch(err => {
          this.clearHealthCode();
          healthCardUtil.log('【healthCardByHealthCode 结果】', err);
          reject(err);
        });
    });
  }
  // 通过code获取健康卡信息
  getInfoByCode() {
    return new Promise((resolve, reject) => {
      if (!this.regInfoCode) {
        healthCardUtil.toast('regInfoCode 不存在');
        return reject(new Error('regInfoCode 不存在'));
      }
      const param = {
        code: this.regInfoCode,
      };
      healthCardUtil.log('getRegInfoByCode 参数】', param);
      getRegInfoByCode(param)
        .then(res => {
          healthCardUtil.log('getRegInfoByCode 结果】', res);
          this.clearRegInfoCode();
          resolve(res);
        })
        .catch(err => {
          this.clearRegInfoCode();
          healthCardUtil.log('getRegInfoByCode 结果】', err);
          reject(err);
        });
    });
  }
  // 获取健康卡信息
  getInfo() {
    if (this.healthCode) {
      return this.getInfoByHealthCode();
    } else if (this.regInfoCode) {
      return this.getInfoByCode();
    } else {
      return new Promise(resolve => {
        resolve('');
      });
    }
  }
  clearInfoCode() {
    this.clearHealthCode();
    this.clearRegInfoCode();
  }

  // 拼接患者id
  generatePatientURL(defaultUrl, patientId) {
    if (patientId) {
      if (defaultUrl.indexOf('?') >= 0) {
        return `${defaultUrl}&patientId=${patientId}`;
      } else {
        return `${defaultUrl}?patientId=${patientId}`;
      }
    }
    return defaultUrl;
  }

  // 人脸识别-设备检测
  checkIsSupportFacialRecognition() {
    return new Promise(resolve => {
      uni.checkIsSupportFacialRecognition({
        checkAliveType: 2, // 优先屏幕闪烁，不支持则读数字
        success: res => {
          console.log(res, '设备检测');
          const systemInfo = uni.getSystemInfoSync();
          if (systemInfo.platform === 'android') {
            const isSupport = res.errCode === 0;
            resolve({
              support: isSupport,
              message: isSupport ? '支持' : '设备不支持',
            });
          } else {
            resolve({
              support: true,
              message: '支持',
            });
          }
        },
        fail: err => {
          console.log(err, '设备检测异常');
          const { errCode } = err;
          const messageEnum = {
            10001: '不支持人脸采集：设备没有前置摄像头',
            10002: '不支持人脸采集：没有下载到必要模型',
            10003: '不支持人脸采集：后台控制不支持',
          };
          resolve({
            support: false,
            message: `${messageEnum[errCode] || '检测失败'}`,
            details: err,
          });
        },
        complete: () => {},
      });
    });
  }
  // 人脸识别
  startFacialRecognitionVerify({ name, idCardNumber }) {
    return new Promise(resolve => {
      uni.startFacialRecognitionVerify({
        name,
        idCardNumber,
        success: resolve,
        fail: err => {
          const { verifyResult } = err;
          resolve({ errCode: -1, verifyResult });
        },
      });
    });
  }
  // 人脸识别-校验
  async verifyFlow({ orderId, verifyType }) {
    return new Promise(async (resolve, reject) => {
      try {
        if (!orderId) {
          healthCardUtil.toast('orderId 不能为空');
          reject(new Error(`orderId 不能为空`));
          return;
        }
        if (!verifyType) {
          healthCardUtil.toast('verifyType 不能为空');
          reject(new Error(`verifyType 不能为空`));
          return;
        }
        // 检测设备
        const supportResult = await this.checkIsSupportFacialRecognition();
        if (!supportResult.support) {
          healthCardUtil.toast(supportResult.message);
          reject(new Error(supportResult.message));
          return;
        }
        healthCardUtil.log('【getOrderInfoByOrderId 参数】', {
          orderId,
          verifyType,
        });
        // 1.获取用户信息
        const healthCardInfoRes = await getOrderInfoByOrderId({
          orderId,
          verifyType,
        });
        healthCardUtil.log('【getOrderInfoByOrderId 结果】', healthCardInfoRes);

        const { name, idCard, cardType } = healthCardInfoRes.data;

        // 2.拉起人脸识别
        const verifyRes = await this.startFacialRecognitionVerify({
          name,
          idCardNumber: idCard,
        });
        healthCardUtil.log('【人脸识别 结果】', verifyRes);
        const { errCode } = verifyRes;
        // 3.获取wechatCode
        const wechatCode = await this.loadWechatCode();
        const param = {
          orderId,
          verifyType,
          result: errCode === 0 ? '01' : '-1',
          name,
          idCard,
          cardType,
          wechatCode,
        };
        healthCardUtil.log('【registerRealPersonAuthOrder 参数】', param);

        // 4.人脸识别验证结果
        const res = await registerRealPersonAuthOrder(param);
        healthCardUtil.log('【registerRealPersonAuthOrder 结果】', res);
        resolve(res.data);
      } catch (err) {
        healthCardUtil.log('【verifyFlow 结果】', err);
        reject(err);
      }
    });
  }

  // 生成二维码
  generateQrCode(healthCardInfo) {
    return new Promise((resolve, reject) => {
      const { idType, idNumber, healthCardId } = healthCardInfo;
      const param = {
        healthCardId,
        idType,
        idNumber,
        codeType: 1, // 静态
      };
      healthCardUtil.log('getDynamicQrCode 参数】', param);
      getDynamicQrCode(param)
        .then(res => {
          healthCardUtil.log('getDynamicQrCode 结果】', res);
          const { qrCodeImg } = res.data;
          if (qrCodeImg) {
            resolve(qrCodeImg);
          } else {
            healthCardUtil.toast('二维码不存在');
            reject(new Error('二维码不存在'));
          }
        })
        .catch(err => {
          healthCardUtil.log('getDynamicQrCode 结果】', err);
          reject(err);
        });
    });
  }

  // 新增-根据健康卡建档
  createByHealthCard(healthCardInfo) {
    return new Promise(async (resolve, reject) => {
      try {
        const param = healthCardUtil.transferInfoByHealthCard(healthCardInfo);
        // 校验地址,未通过去完善
        if (!param.address) {
          // 记录健康卡信息
          this.healthCardInfo = healthCardInfo;
          uni.navigateTo({
            url: '/patientPages/patient/healthAddress/index',
          });
          return reject(new Error('地址不存在'));
        }
        const qrCode = await this.generateQrCode(healthCardInfo);
        console.log('【二维码】', qrCode);
        const params = {
          ...param,
          type: 1, // 地址类型 1-就诊人现住址2-就诊人户籍住址3-物流配送地址
          syncHis: 1,
          qrCodeText: qrCode,
        };
        // 院内建档
        console.log('【院内建档 参数】', params);
        const resAdd = await addHealthCard(params);
        console.log('【院内建档 结果】', resAdd);
        resolve(resAdd);
      } catch (error) {
        reject(error);
      }
    });
  }
  // 更新-根据健康卡建档
  updateByHealthCard(healthCardInfo, patientId) {
    return new Promise(async (resolve, reject) => {
      try {
        if (!patientId) {
          return reject(new Error('patientId 不存在'));
        }
        const param = healthCardUtil.transferInfoByHealthCard(healthCardInfo);
        // 校验地址,未通过去完善
        if (!param.address) {
          // 记录健康卡信息
          this.healthCardInfo = healthCardInfo;
          uni.navigateTo({
            url: `/patientPages/patient/healthAddress/index?patientId=${patientId}`,
          });
          return reject(new Error('地址不存在'));
        }

        const qrCode = await this.generateQrCode(healthCardInfo);
        console.log('【二维码】', qrCode);

        // 已建档更新
        const { relation, phone, nation, address, healthCardId } = param;
        // 更新建档
        const params = {
          platPatientId: patientId,
          qrCodeText: qrCode,
          nation,
          phone,
          address,
          healthCardId,
          type: 1,
          syncHis: 1,
        };
        if (relation) {
          params.relation = relation;
        }
        console.log('【更新建档 参数】', params);
        const resUpdate = await updateHealthCard(params);

        console.log('【更新建档 结果】', resUpdate);
        resolve(resUpdate);
      } catch (error) {
        reject(error);
      }
    });
  }
  // 使用健康卡信息
  getHealthCardInfo() {
    const healthCardInfo = cloneDeep(this.healthCardInfo);
    this.healthCardInfo = null;
    return healthCardInfo;
  }
}

export default new ElectronicHealthCard();
